package com.ddone.aop.annotation.advice;

import lombok.extern.slf4j.Slf4j;
import org.aopalliance.aop.Advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Modifier;
import java.util.Arrays;

/**
 * @author ddone
 * @date 2024/3/19-22:11
 */
@Component
@Slf4j
@Aspect
public class TxAdvice implements Advice {
    /*
     * TODO: 切点类内提取 【本类】
     *     1. 在增强类内，定义一个方法！ 返回值必须是void没有形参列表，名称随意定义！
     *     2. 方法上添加！PointCut（切点表达式）注解
     *     3. 增强引用添加引用切点方法即可 @Before("pc()")
     *
     * TODO:类外提取 【其他类】
     *     1. 外部创建一个类，专门存储切点表达式
     *     2. 增强类内，调用外部类的全限定符+方法名即可
     *     @Before("com.xxx.advice.xxx.txPc()")
     */

    // 定义切点 #1.提取切点，到方法上
    @Pointcut("execution(* com.*.aop.*.impl.*.*(..))")
    public void txPointCut() {
    }

    /**
     *
     * 四个通用属性 通过joinPoint可以提取到
     *  类名: getSimpleName
     *  方法名 getSignature
     *  参数列表 getArgs
     *  修饰符 getModifiers
     * @param joinPoint joinPoint 包含了目标方法信息的对象！
     */
    @Before("txPointCut()")
    public void start(JoinPoint joinPoint) {
        //获取目标方法的信息


        // 目标方法所属的类
        //获取方法的目标对象，获取目标对象的类模板对象，类模板对象获取类名称！
        String simpleName = joinPoint.getTarget().getClass().getSimpleName();
        log.info("className = " + simpleName);

        // 目标方法名
        String name = joinPoint.getSignature().getName();
        log.info("methodName = " + name);

        // 参数列表
        Object[] args = joinPoint.getArgs();
        log.info("argList="+Arrays.toString(args));

        // 目标方法访问修饰符
        int modifiers = joinPoint.getSignature().getModifiers();
        String s = Modifier.toString(modifiers);
        log.info("Method Modifier = " + s);

        // 目标方法的返回结果  不是通用属性 正常执行完毕获取返回值
        // 目标方法的异常信息  不是通用属性 异常增强代码

        log.info("begin transaction");
    }

    // 事务提交 没有提取切点
    // @AfterReturning(value = "execution(* com..impl.*.*(..))",returning = "result")
    @AfterReturning(value = "com.ddone.aop.annotation.advice.TxAdvice.txPointCut()",returning = "result")
    //方法正常执行 不报错
    public void commit(JoinPoint joinPoint, Object result){
        log.info("commit transaction..........");
        log.info("result="+result);
    }

}
